import time
import re
import datetime
import cn2an



char_list_10 = ['零','一','二','三','四','五','六','七','八','九','十']
char_list_12 = ['零','一','二','三','四','五','六','七','八','九','十','十一','十二']
char_list_24 = char_list_12 + ['十三','十四','十五','十六','十七','十八','十九','二十','二十一','二十二','二十三']
char_list_31 = char_list_24 + ['二十四','二十五','二十六','二十七','二十八','二十九','三十','三十一']
char_list_60 = char_list_31[:-2]
for x in '三四五':
    for y in ['']+char_list_10[1:-1]:
        char_list_60.append(x+'十'+y)
date_list = ['今天','明天','后天','大后天','大大后天']
week_num_list = ['日','一','二','三','四','五','六']
week_list = ['周'+x for x in week_num_list]


def find_all(pat, text):
    pos_span = []
    for r in re.finditer(pat, text):
        pos_span.append([r.start(), r.group()])
    return pos_span

def char2digit(t):
    try:
        r=int(cn2an.transform(t))
    except Exception as e:
        r=-1
        print('汉字转数字错误',e)
    return r


def convert_date(date):
    # 日期转时间戳（秒）
    date = time.strptime(date, "%Y-%m-%d %H:%M")
    date = int(time.mktime(date))
    return date

def get_date(timeStamp):
    # 时间戳（秒）转日期
    if not timeStamp:
        return 'None'
    timeArray = time.localtime(int(str(timeStamp)))
    return time.strftime("%Y-%m-%d %H:%M", timeArray)


def add_date(year,month,day,n):
    # 加日期
    year, month, day = str(year),str(month),str(day)
    if len(month)==1:
        month = '0'+month
    if len(month) == 1:
        day = '0' + day
    t = f"{year}-{month}-{day} 00:00"
    t = convert_date(t) + n * 25*3600
    t = get_date(t)
    year, month, day = t.split(' ')[0].split('-')
    year, month, day = int(year), int(month), int(day)
    return year, month, day

def add_time(year,month,day,hour,minute,add_hour,add_minute):
    # 加小时分钟
    year, month, day = str(year),formate(month),formate(day)
    hour, minute = formate(hour),formate(minute)

    t = f"{year}-{month}-{day} {hour}:{minute}"
    t = convert_date(t) + add_hour * 3600 + add_minute * 60
    t = get_date(t)
    day,tim = t.split(' ')
    year, month, day = day.split('-')
    year, month, day = int(year), int(month), int(day)
    hour, minute = tim.split(':')
    hour, minute = int(hour), int(minute)
    return year,month,day,hour,minute

def formate(x):
    if type(x) == str:
        x = int(x)
    if x < 10:
        return '0' + str(x)
    else:
        return str(x)

def fun(text, context={}):
    '''
    时间实体解析
    :param text:当前对话的时间实体，str
    :param context: 上一轮的解析结果
    :return: result = {
        'time': '21:00', # 时间点
        'date': '2023-03-21', # 日期
        'repeat': '0000000', # 循环
        'keyword':[], # 上午下午关键词
        'valid': False # 结果是否有效
    }
    '''
    # print('-'*5,'\t',text)
    result = {
        'time': context.get('time',''), # 时间点
        'date': context.get('date',''), # 日期
        'repeat': context.get('repeat','0000000'), # 循环
        'keyword':context.get('keyword',[]), # 上午下午关键词
        'valid': context.get('valid',False) # 结果是否有效
    }

    # 时间点默认值
    if result['time']:
        sp_time = result['time'].split(':')
        if len(sp_time) == 2:
            # 用上一轮值
            target_hour, target_minute = sp_time
            target_hour, target_minute = int(target_hour),int(target_minute)
        else:
            target_hour, target_minute = -1,-1
    else:
        target_hour, target_minute = -1,-1




    text = text.replace('礼拜','周').replace('星期','周').replace('每个','每').replace('周天','周日')
    today = datetime.datetime.now()
    today_date = today.date()
    now_time = today.time()
    now_year = today_date.year
    now_month = today_date.month
    now_day = today_date.day
    now_week = (today.weekday() + 1) % 7
    now_hour = now_time.hour
    now_minute = now_time.minute
    # print('now_year',now_year)
    # print('now_month',now_month)
    # print('now_day',now_day)
    # print('now_week',now_week)
    # print('now_hour',now_year)
    # print('now_minute',now_minute)
    repeat = list(map(int,result['repeat']))
    day_part_keyword = ['凌晨','清晨','早晨','上午','中午','午后','下午','傍晚','晚上','夜晚']
    day_part = [x for x in day_part_keyword if x in text]
    find_date = False
    if day_part:
        result['keyword'] = day_part

    # 年月日默认值
    if result['date']:
        sp_date = result['date'].split('-')
        if len(sp_date) == 3:
            # 用上一轮值
            target_year, target_month, target_day = sp_date
            target_year, target_month, target_day = int(target_year.lstrip('0')), int(target_month.lstrip('0')), int(target_day.lstrip('0'))
            find_date = True
        else:
            target_year, target_month, target_day = now_year, now_month, now_day
    else:
        target_year, target_month, target_day = now_year, now_month, now_day


    # 几时几分后
    p = f"({'|'.join(char_list_31)})?小?时?({'|'.join(char_list_60)})?分?钟?后"
    for r in re.finditer(p, text):
        time_text = r.group()
        add_hour = 0
        add_minute = 0
        hour_text, minute_text = '',''
        if '小时' in time_text:
            hour_text = time_text[:time_text.index('小时')]
            time_text = time_text.replace(hour_text+'小时','')
        elif '时' in time_text:
            hour_text = time_text[:time_text.index('小时')]
            time_text = time_text.replace(hour_text+'时','')
        if hour_text:
            add_hour = char2digit(hour_text)

        if '分钟' in time_text:
            minute_text = time_text[:time_text.index('分钟')]
        elif '分' in time_text:
            minute_text = time_text[:time_text.index('分')]
        if minute_text:
            add_minute = char2digit(minute_text)
        if add_hour>0 or add_minute>0:
            target_year, target_month, target_day, target_hour, target_minute = add_time(now_year,now_month,now_day,now_hour,now_minute,add_hour,add_minute)
            text = text.replace(time_text, '#')

    # print('后text',text)
    # 抽取月日
    p = f"({'|'.join([x+'月' for x in char_list_12])})?({'|'.join(char_list_31)})(日|号)"
    for r in re.finditer(p, text):
        time_text = r.group()
        text = text.replace(time_text,'#')
        if '月' in time_text:
            target_month = char2digit(time_text[:time_text.index('月')])
            time_text = time_text[time_text.index('月')+1:]
        target_day = char2digit(time_text[:-1])
        find_date = True
    # print('月日text',text)

    # 抽取时间点
    p = f"({'|'.join(char_list_24)})点({'|'.join(char_list_10)})*(半|刻)?"
    for r in re.finditer(p, text):
        time_text = r.group()
        # time_pos = r.start()
        text = text.replace(time_text,'#')
        hour,minute = time_text.split('点')
        # print('hour,minute',hour,minute)
        hour = char2digit(hour)
        target_hour = hour
        # 分钟处理
        if minute =='半':
            minute = 30
        elif minute == '一刻':
            minute = 15
        elif minute == '三刻':
            minute = 45
        elif minute:
            minute = char2digit(minute)
        else:
            minute = -1
        target_minute = minute


        if [x for x in ['晚上','夜晚'] if x in result['keyword']] and 0<hour<4:
            target_hour = hour
        elif '中午' in result['keyword'] and hour<5:
            target_hour = hour+12
        elif [x for x in ['午后','下午','傍晚','晚上','夜晚'] if x in result['keyword']] and hour<12:
            target_hour = hour+12
        else:
            target_hour = hour

        if not find_date and hour<now_hour or (hour==now_hour and minute<now_minute):
            target_year, target_month, target_day = add_date(now_year,now_month,now_day,1)

        if target_hour > -1 and target_minute == -1:
            target_minute = 0
    # print('时间点text',text)


    # print('hour',target_hour)
    # print('minute',target_minute)

    # 今明后
    for i,d in enumerate(date_list):
        if d in text:
            target_year,target_month,target_day = add_date(now_year,now_month,now_day,i)

    # 每天每周
    if '工作日' in text:
        target_year, target_month, target_day = '', '', ''
        repeat = [0,1,1,1,1,1,0]
    if '周末' in text:
        target_year, target_month, target_day = '', '', ''
        repeat = [1,0,0,0,0,0,1]

    if '每' in text:
        target_year, target_month, target_day = '', '', ''
        find_week = find_all(f"周?({'|'.join(week_num_list)})",text)
        if find_week:
            pos_week = []
            for pos, week in find_week:
                if week[0]=='周':
                    week = week[1:]
                pos_week.append([pos,week_num_list.index(week)])
            mid_span = text[min([x[0] for x in pos_week]):max([x[0] for x in pos_week])]
            p=False
            if '到' in mid_span or '至' in mid_span:
                for i in range(len(pos_week)):
                    pos, week = pos_week[i]
                    if p:
                        last_week = pos_week[i - 1][1]
                        if last_week<=week:
                            for j in range(last_week,week+1):
                                repeat[j]=1
                        else:
                            target = list(range(0,week+1))+list(range(last_week,7))
                            for j in target:
                                repeat[j] = 1
                        p=False
                    repeat[week] = 1
                    if i < len(pos_week)-1:
                        next_pos = pos_week[i+1][0]
                        mid_span = text[pos:next_pos]
                        if '到' in mid_span or '至' in mid_span:
                            p=True

            else:
                for pos, week in pos_week:
                    repeat[week]=1
        else:
            repeat = [1 for _ in range(7)]
    else:
        find_week = find_all(f"下*周?({'|'.join(list('日一二三四五六'))})", text)
        if find_week:
            num_next_week = text.count('下')
            week = -1
            for pos, week in find_week:
                week = week[-1]
                week=week_num_list.index(week)
                break
            if num_next_week == 0:
                print('week',week,now_week)
                if week == now_week:
                    if target_hour < now_hour or (target_hour == now_hour and target_minute < now_minute):
                        target_year, target_month, target_day = add_date(now_year, now_month, now_day, 7)
                elif week < now_week:
                    target_year, target_month, target_day = add_date(now_year, now_month, now_day, 7-(now_week-week))
                else:
                    target_year, target_month, target_day = add_date(now_year, now_month, now_day, week-now_week)
            else:
                target_year, target_month, target_day = add_date(now_year, now_month, now_day, 7*num_next_week+week-now_week)



    if target_hour>=0 and target_minute>=0:
        result['time'] = f'{formate(target_hour)}:{formate(target_minute)}'
    if target_month and target_day:
        result['date'] = f'{target_year}-{formate(target_month)}-{formate(target_day)}'
    else:
        result['date'] = ''
    result['repeat'] = ''.join(map(str,repeat))
    if result['time']:
        result['valid'] = True

    # for k,v in result.items():
    #     print(k,':',v)

    return result

def test():
    # 多轮测试
    text = input('输入：')
    r = fun(text)
    while not r['valid']:
        text = input('再输入：')
        r = fun(text,r)
    print('*\t结束')
    for k,v in r.items():
        print(k,':',v)


if __name__ == '__main__':
    test()

    exit()
    # print(add_date(2023,2,28,1))
    #
    # exit()
    # t="2023-02-12 12:45"
    # a=convert_date(t)
    # print(a)
    # b=get_date(a)
    # print(b)

    fun('三点半')
    fun('明天三点半')
    fun('大后天三点半')
    fun('每天下午三点半')
    fun('每周三的一点半')
    fun('每周三五一的四点三十五分')
    fun('周末四点三十五分')
    fun('工作日的四点三十五分')





